using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace OpenRay
{
	//Immutable class
	public class ReflectivePhongMaterial : PhongMaterial
	{
		private readonly List<Color> reflectivity = new List<Color>(2);
		protected readonly IScene scene;
		
		public ReflectivePhongMaterial ( IList<Color> a, IList<Color> d, IList<Color> s, IList<Color> e, 
		                                 IList<float> sh, IList<Color> r, IScene sc )
			: base ( a, d, s, e, sh )
		{
			Debug.Assert( r.Count == 2, "Incorrect size of reflective term provided" );
			reflectivity.AddRange( r );
			
			scene = sc;
		}
		
		protected Color ReflectiveMaterialShade(Point worldHit, Point ModelHit, Vector normalizedViewer, Vector surfaceNormal, Face f, uint depth)
		{
			Ray r = new Ray(worldHit, Vector.Reflect(normalizedViewer, surfaceNormal) );
			IList<PrimitiveHit> hits = scene.Trace(r, depth);
			
			return ( hits.Count > 0 ) ? hits[0].Shade(r) * reflectivity[(int)f]: new Color(0, 0, 0, 1);
		}

		public override Color Shade( Point worldHit, Point ModelHit, Vector normalizedViewer, Vector surfaceNormal, IList<Light> lights, Material.Face f, uint depth ) {
			return PhongMaterialShade(worldHit, ModelHit, normalizedViewer, surfaceNormal, lights, f ) +
				   ReflectiveMaterialShade(worldHit, ModelHit, normalizedViewer, surfaceNormal, f, depth);
		}
		
		public override Color Shade( Point worldHit, Point ModelHit, Vector normalizedViewer, Vector surfaceNormal, IList<Light> lights, uint depth ) {
			Material.Face f = FaceHit(normalizedViewer, surfaceNormal);
			
			return PhongMaterialShade(worldHit, ModelHit, normalizedViewer, surfaceNormal, lights, f ) +
				   ReflectiveMaterialShade(worldHit, ModelHit, normalizedViewer, surfaceNormal, f, depth);
		}
	}
}

